package com.miplus.ccrm.admin.config;

import com.fasterxml.jackson.databind.exc.InvalidFormatException;
import com.miplus.ccrm.common.EnumRCode;
import com.miplus.ccrm.common.R;
import com.miplus.ccrm.common.ServiceException;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.type.TypeException;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.validation.BindException;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import javax.validation.ConstraintViolationException;

@RestControllerAdvice(basePackages = "com.miplus.ccrm")
@Slf4j
public class ExceptionAdvice {
    /**
     * {@code @PathVariable} 和 {@code @RequestParam} 参数校验不通过时抛出的异常处理
     */
    @ExceptionHandler({ConstraintViolationException.class})
    public R<?> handleConstraintViolationException(ConstraintViolationException ex) {
        log.error("ConstraintViolationException",ex);
        return R.Error(EnumRCode.ArgErr, ex.getMessage());
    }

    /**
     * 参数类型不通过时抛出的异常处理
     */
    @ExceptionHandler({TypeException.class})
    public R<?> handleTypeException(TypeException ex) {
        log.warn("TypeException",ex);
        return R.Error(EnumRCode.ArgErr, ex.getMessage());
    }

    /**
     * 参数校验不通过时抛出的异常处理
     */
    @ExceptionHandler({BindException.class})
    public R<?> handleBindException(BindException ex) {
        log.warn("BindException",ex);
        return R.Error(EnumRCode.ArgErr, ex.getMessage());
    }

    /**
     * 参数输入错误，比如整型数输入太长16位之类的HttpMessageNotReadableException
     */
    @ExceptionHandler({InvalidFormatException.class})
    public R<?> handleInvalidFormatException(InvalidFormatException ex) {
        log.warn("InvalidFormatException",ex);
        return R.Error(EnumRCode.ArgErr, ex.getMessage());
    }

    /**
     * 参数输入错误，比如整型数输入太长16位之类的
     */
    @ExceptionHandler({HttpMessageNotReadableException.class})
    public R<?> handleHttpMessageNotReadableException(HttpMessageNotReadableException ex) {
        log.warn("HttpMessageNotReadableException:{}",ex.getMessage());
        return R.Error(EnumRCode.ArgErr, ex.getMessage());
    }

    @ExceptionHandler({ServiceException.class})
    public R<?> handle(ServiceException ex) {
        log.warn("ServiceException:code={},message={}",ex.getCode(),ex.getMessage());
        return R.Error(ex.getCode(), ex.getMessage());
    }

    @ExceptionHandler({RuntimeException.class})
    public R<?> handle(RuntimeException ex) {
        log.error("RuntimeException",ex);
        return R.Error(EnumRCode.RuntimeException,ex.getMessage());
    }

    @ExceptionHandler({MethodArgumentNotValidException.class})
    public R<?> handle(MethodArgumentNotValidException ex) {
        log.error("MethodArgumentNotValidException",ex);
        return R.Error(EnumRCode.ArgErr,ex.getMessage());
    }

    /**
     * 顶级异常捕获并统一处理，当其他异常无法处理时候选择使用
     */
    @ExceptionHandler({Exception.class})
    public R<?> handle(Exception ex) {
        log.error("TopException",ex);
        return R.Error(EnumRCode.Exception,ex.getMessage());
    }
}
